/*
 * Copyright (C) 2017 adorsys GmbH & Co. KG
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package de.adorsys.ohos.securestoragelibrary;

import ohos.agp.render.render3d.BuildConfig;
import ohos.app.Context;
import ohos.app.Environment;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;

import java.io.File;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Base64;

import static de.adorsys.ohos.securestoragelibrary.SecureStorageException.ExceptionType.CRYPTO_EXCEPTION;
import static de.adorsys.ohos.securestoragelibrary.SecureStorageException.ExceptionType.KEYSTORE_EXCEPTION;

public final class KeystoreTool {
    private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x000110, "KeystoreTool");
    private static final String KEY_ALIAS = "rsaKeyPair";
    private static String path;

    private KeystoreTool() {
    }

    // 加密信息
    static String encryptMessage(Context context, String plainMessage) throws SecureStorageException {
        try {
            PublicKey publicKey = getPublicKey(context);
            byte[] encrypt = RsaUtils.encrypt(plainMessage.getBytes(), publicKey);
            HiLog.debug(LABEL, "encrypted: " + Base64.getEncoder().encodeToString(encrypt));
            return Base64.getEncoder().encodeToString(encrypt);
        } catch (Exception e) {
            HiLog.error(LABEL, e.getMessage());
            throw new SecureStorageException(e.getMessage(), e, KEYSTORE_EXCEPTION);
        }
    }

    public static String decryptMessage(Context context, String encryptedMessage) throws SecureStorageException {
        try {
            PrivateKey privateKey = getPrivateKey(context);
            byte[] enMessage = Base64.getDecoder().decode(encryptedMessage.getBytes());
            byte[] priKeyStores = RsaUtils.decrypt(enMessage, privateKey);
            HiLog.info(LABEL, new String(priKeyStores));
            return new String(priKeyStores);
        } catch (Exception e) {
            throw new SecureStorageException(e.getMessage(), e, CRYPTO_EXCEPTION);
        }
    }

    // 判断密钥对是否存在
    public static boolean keyPairExists(Context context) {
        path = context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS)
            .getAbsolutePath() + File.separator;
        File publicKey = new File(path + "pub.txt");
        File privateKey = new File(path + "pri.txt");
        HiLog.info(LABEL, "公/私钥是否存在 " + publicKey.exists() + " " + publicKey.exists());
        if (!publicKey.exists() && !privateKey.exists()) {
            return false;
        } else {
            return true;
        }
    }



    public static void generateKeyPair(Context context) {
        // 随机生成一对密钥（包含公钥和私钥）
        if (!keyPairExists(context)) {
            try {
                KeyPair keyPair = RsaUtils.generateKeyPair();
                PublicKey pubKey = keyPair.getPublic();
                PrivateKey priKey = keyPair.getPrivate();
                RsaUtils.saveKeyForEncodedBase64(pubKey, new File(path + "pub.txt"));
                RsaUtils.saveKeyForEncodedBase64(priKey, new File(path + "pri.txt"));
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else if (BuildConfig.DEBUG) {
            HiLog.debug(LABEL, context.getString(ResourceTable.String_message_keypair_already_exists));
        }
    }

    static void deleteKeyPair( Context context) throws SecureStorageException {
        // Delete Key from Keystore
        if (keyPairExists(context)) {
            try {
                getKeyStoreInstance().deleteEntry(KEY_ALIAS);
            } catch (KeyStoreException e) {
                throw new SecureStorageException(e.getMessage(), e, KEYSTORE_EXCEPTION);
            }
        } else if (BuildConfig.DEBUG) {
            HiLog.error(LABEL, KeystoreTool.class.getName() + "keypair 不存在");
        }
    }


    private static PublicKey getPublicKey( Context context) throws Exception {
        PublicKey publicKey;
        publicKey = RsaUtils.getPublicKey(IoUtils.readFile(new File(path + "pub.txt")));
        HiLog.info(LABEL, "getPublicKey " + publicKey);
        return publicKey;
    }

    private static PrivateKey getPrivateKey( Context context)  {
        PrivateKey privateKey = null;
        path = context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath()
            + File.separator;
        HiLog.debug(LABEL, "key store path:  "+path);
        try {
            privateKey = (PrivateKey) RsaUtils.getPrivateKey(IoUtils.readFile(new File(path + "pri.txt")));
        } catch (Exception e) {
            HiLog.info(LABEL, e.getMessage());
            e.printStackTrace();
        }
        return privateKey;
    }

    private static KeyStore getKeyStoreInstance() throws SecureStorageException {
        try {
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null, null);
            return keyStore;
        } catch (Exception e) {
            HiLog.error(LABEL, e.getMessage());
            throw new SecureStorageException(e.getMessage(), e, KEYSTORE_EXCEPTION);
        }
    }
}